package cn.virens.common.boot.filter.ajax;

import cn.virens.common.spring.filter.AbstractPathMatcherFilter;
import cn.virens.common.util.core.crypto.AesUtil;
import cn.virens.common.util.core.network.RequestUtil;
import cn.virens.common.util.exception.APIException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.hutool.core.convert.ConvertUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.web.cors.CorsUtils;

import java.io.IOException;

@SuppressWarnings("unused")
public class SimpleHandlerAjaxSignFilter extends AbstractPathMatcherFilter {
    private SimpleHandlerAjaxSignProperties properties;

    public SimpleHandlerAjaxSignFilter(SimpleHandlerAjaxSignProperties properties) {
        this.properties = properties;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (preHandle0(request, response)) filterChain.doFilter(request, response);
    }

    private boolean preHandle2(HttpServletRequest request, HttpServletResponse response, String sign, String timestamp) throws APIException {
        if (sign != null && StrUtil.equals(sign, AesUtil.md5(timestamp + properties.getAuthSign()))) {
            return !properties.getAuthStrict() || isTimeout(ConvertUtil.toLong(timestamp, 0L));
        } else {
            throw new APIException("SIGN_ERR", "签名错误");
        }
    }

    private boolean preHandle1(HttpServletRequest request, HttpServletResponse response) throws APIException {
        String timestamp = RequestUtil.getHeader(request, properties.getHeadersTimestamp());
        String platform = RequestUtil.getHeader(request, properties.getHeadersPlatform());
        String sign = RequestUtil.getHeader(request, properties.getHeadersSign());

        return preHandle2(request, response, sign, timestamp);
    }

    private boolean preHandle0(HttpServletRequest request, HttpServletResponse response) throws APIException {
        return CorsUtils.isPreFlightRequest(request) || preHandle1(request, response);
    }

    private boolean isTimeout(long timestamp) throws APIException {
        var tm_diff = System.currentTimeMillis() - timestamp;

        return tm_diff > properties.getAuthTimeout();
    }
}
